/*
 * Darts playing model for CS181.
 */

#include "darts.h"

/* Initialize the wedges and angles arrays */
int wedges[NUM_WEDGES] = WEDGES;

void init_board() {
  int i,j;

  for (i=0; i<NUM_WEDGES; i++) {
    j = wedges[i];
    angles[j] = i;
  }
}

/* Computes and stores all possible actions 
 * (locations on the dart board) in the given pointer to an array. 
 */
void get_actions(location *actions) {
    int r, w, i = 0;
	
    for (r = 0; r <= 5; r++) {
        for (w = 0; w < NUM_WEDGES; w++) {
            actions[i].ring = r;
            actions[i].wedge = wedges[w];
            i++;
        }
    }
}

/* <CODE HERE>: Implement the reward function.
 */
float R(int s, location a) {
    return (s == 0)?1:0;
}

/* Determine the raw score for a board location */

int location_to_score(location loc) {
  int result;

  switch (loc.ring) {
  case CENTER : result = 2.5 * NUM_WEDGES; break;
  case INNER_RING : result = 1.25 * NUM_WEDGES; break;
  case FIRST_PATCH : result = loc.wedge; break;
  case MIDDLE_RING : result = 3 * loc.wedge; break;
  case SECOND_PATCH : result = loc.wedge; break;
  case OUTER_RING : result = 2 * loc.wedge; break;
  default : result = 0;
  }

  return result;
}

/* Play a single game */
int play(void) {
  int raw_score, score, turns;
  location action, result;

  score = START_SCORE;
  turns = 0;

  action = start_game(GAMMA);

  do {
	printf("Current score: %d\n", score); 

    turns++;
    result = throw(action);
    raw_score = location_to_score(result);
    
    
    printf("Target: wedge %d, ring %d\n", action.wedge, action.ring);
    printf("Result: wedge %d, ring %d\n", result.wedge, result.ring);
    printf("Score: %d%s\n\n", raw_score, raw_score>score ? " TOO HIGH!" : "");
    

    if (raw_score <= score) {
      score -= raw_score;
    }
    if (score == 0) break;
    action = get_target(score);
  } while (1);

    printf("WOOHOO!  It only took %d turns\n", turns); 

  return turns;
}

/* Play n games and return the average score */

void test(int n) {
  int score, i;

  for (i=0,score=0;i<n;i++) {
    score += play();
  }

  printf("Average turns = %f\n", (float)score/(float)n);
}


/* <CODE HERE>: Feel free to modify the main function to set up your experiments. */

extern location pi_star[];
extern float V[];

int main(int argc, char **argv) {

  float T_matrix[NUM_STATES][NUM_STATES][NUM_ACTIONS];

/* Set the random number generator to a particular seed to establish a particular
   throwing model, and then initialize the throwing model with init_thrower(). */
  srand(42); // Constant seed for consistency in testing
  init_board();
	
/*********************************************************
* Run a single game with the probability distribution 
* and MDP defined in question 2, and use "make mdp."
*********************************************************/
/*
	use_simple_thrower(); 
	test(100); 
  */
/*********************************************************
* Prints out stationary policy for various gamma
*********************************************************/
/*
  for (double g = 0.01; g < 1; g += 0.01) {
    start_game(g);
    printf("\n\n*** GAMMA: %f ***\n", g);
    printf("Score\tTWedge\tTRing\tTScore\tProb\n");
    for (int score=START_SCORE; score>=1; score--) {
      location pi_star = get_target(score);
      printf("%d\t%d\t%d\t%d\t%f\n", score, pi_star.wedge, pi_star.ring, location_to_score(pi_star), T(location_to_score(pi_star),0,pi_star));
    }
	}
  */
/*********************************************************
* Run the model-based RL algorithm, and use 
* "make modelbased."
*********************************************************/
	
	/*init_thrower();
	for (int epoch=10; epoch<2000; epoch+=10) {
    modelbased(GAMMA, epoch, T_matrix, 100); 
  }*/
  
/*********************************************************
* Run the model-free RL algorithm, and use 
* "make modelfree." Currently, this simply produces
* a default darts player. For more information, refer
* to modelfree.c.
 *********************************************************/

	init_thrower();
  for(int num_games = 100; num_games<10000; num_games+=100) {
    Q_learning(GAMMA, num_games);
  }
  /*
  for (int num_games = 100; num_games<10000; num_games+=100) {
    modelbased(GAMMA, num_games/20, T_matrix, num_games); 
  }*/ 
}


